home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************
- * PROGRAM: Spades *
- * AUTHOR: Gregory M. Stelmack *
- * COMPILER: Lattice C V5.04 *
- * Copyright (C) 1988 Lattice, Inc. *
- * VESRION DATES: *
- * Version 1.0 -- February 5, 1990 *
- * Version 1.1 -- April 28, 1990 *
- * Images used for cards -- file "Spades.images" *
- * must be in current directory to run. *
- * Title graphics added. New routine for *
- * choosing dealer. *
- * Tab stops set to 2,4,6,8,... for this listing. *
- **********************************************************/
-
- /* Include files */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <exec/libraries.h>
- #include <graphics/gfxmacros.h>
- #include <stdio.h>
- #include <math.h>
- #include <time.h>
- #include <string.h>
- #include <fcntl.h>
-
- /* Structures needed for libraries */
-
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct Library *DiskfontBase;
-
- /* Intuition Structures */
-
- struct Screen *CustScr;
- struct Window *Wdw;
- struct Viewport *WVP;
- struct IntuiMessage *Message;
-
- /************** Program Constants **************/
- #define RP Wdw->RPort /* Raster Port for Graphics Routines */
- #define PENS 8 /* Number of Pens */
- #define DEPTH 3 /* Number of BitPlanes */
- #define MLEFT 1 /* Left Mouse Button Pressed */
- #define MRIGHT 2 /* Right Mouse Button Pressed */
-
- #define DIAMONDS 0 /* Suit Definitions */
- #define CLUBS 1
- #define HEARTS 2
- #define SPADES 3
-
- #define WHITE 0xFFF /* Palette Data */
- #define RED 0xF00
- #define GREEN 0x0F0
- #define BLUE 0x00F
- #define CYAN 0x0FF
- #define PURPLE 0xF0F
- #define YELLOW 0xFF0
- #define BLACK 0x000
-
- /************** Color Map Data *****************/
- static USHORT colormap [PENS] =
- {
- BLUE, /* Pen 0 */
- BLACK, /* Pen 1 */
- RED, /* Pen 2 */
- GREEN, /* Pen 3 */
- WHITE, /* Pen 4 */
- YELLOW, /* Pen 5 */
- PURPLE, /* Pen 6 */
- CYAN /* Pen 7 */
- };
-
- #define BLUP 0
- #define BLKP 1
- #define REDP 2
- #define GRNP 3
- #define WHTP 4
- #define YELP 5
- #define PURP 6
- #define CYNP 7
-
- /************** Text Structure *****************/
- struct TextAttr StdFont =
- {
- "topaz.font",
- TOPAZ_EIGHTY,
- FS_NORMAL,
- FPF_ROMFONT,
- };
-
- /*********** NewScreen Structure **********/
- struct NewScreen NewCustScr =
- {
- 0,0, /* Left Edge, Top Edge */
- 320,200,DEPTH, /* Width, Height, Depth */
- WHTP,BLUP, /* Detail Pen, Block Pen */
- NULL, /* View Mode */
- CUSTOMSCREEN, /* Screen Type */
- &StdFont, /* Pointer to Font */
- NULL, /* Pointer to Title Text */
- NULL, /* Pointer to Screen Gadgets */
- NULL, /* Pointer to CustomBitMap */
- };
-
- /*********** NewWindow Structure **********/
- struct NewWindow NewWdw =
- {
- 0,0, /* Left Edge, Top Edge */
- 320,200, /* Width, Height */
- BLKP,WHTP, /* Block Pen, Detail Pen */
- MOUSEBUTTONS | CLOSEWINDOW, /* IDCMP Flags */
- SMART_REFRESH | ACTIVATE | GIMMEZEROZERO | RMBTRAP | WINDOWCLOSE,
- NULL, /* Pointer to First Gadget */
- NULL, /* Pointer to Check Mark image */
- "Spades, by Greg Stelmack", /* Title */
- NULL, /* Pointer to Screen structure */
- NULL, /* Pointer to custom Bit Map */
- 0,0, /* Minimum Width, Height */
- 0,0, /* Maximum Width, Height */
- CUSTOMSCREEN /* Type of Screen it resides on */
- };
-
- /************************* Image Data *************************/
- struct Image CardImage =
- {
- 0, 0, /* LeftEdge, TopEdge */
- 42, 42, 3, /* Width, Height, Depth */
- NULL, /* Image Data */
- 7, 0, /* PlanePick, PlaneOnOff */
- NULL /* *NextImage */
- };
-
- #include "Spades.h"
-
- /*************************** Arrays ***************************/
-
- /***************************************
- * Deck: status of cards. *
- * 0 = Undealt or played. *
- * 1 thru 4 = Player who holds card. *
- ***************************************/
- int Deck[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- /***************************************
- * Hand: cards in each player's hand. *
- * 0 = Played. *
- * 1 thru 52 = Card number. *
- ***************************************/
- int Hand[4][13] = { {0,0,0,0,0,0,0,0,0,0,0,0,0},
- {0,0,0,0,0,0,0,0,0,0,0,0,0},
- {0,0,0,0,0,0,0,0,0,0,0,0,0},
- {0,0,0,0,0,0,0,0,0,0,0,0,0} };
-
- /********************************************
- * Bid: number of tricks bid by each player. *
- ********************************************/
- int Bid[4] = {0,0,0,0};
-
- /********************************************
- * Mode: aggressiveness of each player. *
- * The number in this array is added to *
- * the strength of the hand to determine *
- * the number of tricks to bid. Higher *
- * number equals more tricks. *
- ********************************************/
- int Mode[4] = {0,0,0,0};
-
- /********************************************
- * SuitPoints: how many points are added to *
- * the strength of a hand depending on the *
- * number of cards in each suit in the *
- * hand. The first row is for non-spades, *
- * the second for spades. *
- ********************************************/
- int SuitPoints[2][14] = { {6,3,1,0,0,0,-2,-4,-6,-8,-10,-12,-20,-50},
- {-4,-2,-1,0,0,+1,+2,+5,+8,+10,+12,+20,+50} };
-
- /********************************************
- * HighCardLeft: the highest unplayed card *
- * in each suit. *
- ********************************************/
- int HighCardLeft[4] = {0,0,0,0};
-
- /********************************************
- * Card: the card played in a trick by each *
- * player. *
- ********************************************/
- int Card[4] = {0,0,0,0};
-
- /********************************************
- * Value: the point value of each card held *
- * in a hand. Used by computer to determine*
- * which card to play. *
- ********************************************/
- int Value[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- /********************************************
- * SuitNumber: the number of cards in each *
- * suit held by a player. *
- ********************************************/
- int SuitNumber[4] = {0,0,0,0};
-
- /********************************************
- * CardX & CardY: The X and Y positions for *
- * the played card for each player. *
- * MsgX & MsgY: The X and Y positions for *
- * single character messages for each *
- * player. *
- ********************************************/
- int CardX[4] = {100,1,100,209};
- int CardY[4] = {99,60,1,60};
-
- int MsgX[4] = {116,45,116,195};
- int MsgY[4] = {96,84,50,84};
-
- /********************************************
- * OutOfSuit: Whether or not a player is out *
- * of a suit. *
- ********************************************/
- BOOL OutOfSuit[4][4] = { {0,0,0,0},
- {0,0,0,0},
- {0,0,0,0},
- {0,0,0,0} };
-
- /******************** Other Global Variables ******************/
- char *String = " "; /* Temporary String Storage */
-
- int PlayerScore=0, CompScore=0, PlayerTricks=0, CompTricks=0;
- int HandLead=0, Button=0, TrickLead=0, PlayerBid=0, CompBid=0;
- int ShortSuit=0, LongSuit=0, HighCard=0, Winner=0;
- BOOL SpadePlayed=FALSE, AllDone=FALSE;
- char *CardData;
-
- SHORT Mx=0, My=0; /* Mouse Coordinates */
-
- /******************** Function Declarations *******************/
- void Spades(), SetUpScreen(), DealCards(), ShowHand(), DrawCard();
- int CalcBid(),GetPlayerBid(), TakeTrick(), GetPlayerCard();
- int GetCompCard(),FindDealer();
- BOOL ValidCard();
- void itoa(), PrintBids(), PrintScore(), PrintTricks(), GetBids();
- void ReadMouse(), PlayHand(), InitVars(), CalcLead(), CalcFollow();
- void FinishRoutine(), WrapUp(), SuggestCard(), CountCards();
- void Title();
-
- /********************* Program Begins Here ********************/
-
- /**********************************************************
- * Function: main *
- * Purpose: Open everything, play the game, close *
- * everything. *
- **********************************************************/
- main()
- {
- int fh;
- unsigned int count=0;
- unsigned int length=0;
-
- /* Open the Intuition and Graphics libraries. */
-
- IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library",LIBRARY_VERSION);
- if (IntuitionBase == NULL)
- {
- printf("Can't open Intuition Library");
- WrapUp();
- }
-
- GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library",LIBRARY_VERSION);
- if (GfxBase == NULL)
- {
- printf("Can't open Graphics Library");
- WrapUp();
- }
-
- /* Open the screen and window */
-
- if ((NewWdw.Screen = CustScr =
- (struct Screen *)OpenScreen(&NewCustScr)) == NULL)
- {
- printf("Can't open new screen");
- WrapUp();
- }
-
- if (( Wdw = (struct Window *)OpenWindow(&NewWdw)) == NULL)
- {
- printf("Can't open new window");
- WrapUp();
- }
-
- /* Find the viewport and load color map */
-
- WVP = (struct ViewPort *)ViewPortAddress(Wdw);
- LoadRGB4(WVP,&colormap,PENS);
-
- /* Seed random number generator with TIMER */
-
- srand(time(NULL));
-
- /* Load Graphic Images */
-
- length=52*126*2*3;
- CardData = (char *)AllocMem(length,MEMF_CHIP);
- if (!CardData)
- {
- printf("Could not allocate image memory!");
- WrapUp();
- }
- fh = open("Spades.images",O_RDONLY,0);
- if (fh==-1)
- {
- printf("Can't open images file!");
- WrapUp();
- }
- count = read(fh,CardData,length);
- if (count==-1)
- {
- printf("Error reading images file!");
- WrapUp();
- }
-
- /* Start Game */
-
- Spades();
-
- /* Close Everything */
-
- WrapUp();
- }
-
- /**********************************************************
- * Function: WrapUp *
- * Parameters: none *
- * Return Values: none *
- * Purpose: close everything and exit *
- **********************************************************/
- void WrapUp()
- {
- if (CardData) FreeMem((char*)CardData,52*126*2);
- if (Wdw) CloseWindow(Wdw);
- if (CustScr) CloseScreen(CustScr);
- if (GfxBase) CloseLibrary(GfxBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- exit(0);
- }
-
- /**********************************************************
- * Function: Spades *
- * Parameters: None *
- * Return Values: None *
- * Purpose: Play a game of spades. Loop until someone *
- * scores 500. *
- **********************************************************/
- void Spades()
- {
- Title();
-
- AllDone=FALSE;
-
- /* Loop until player no longer wants to play. */
-
- while (!AllDone)
- {
- PlayerScore=CompScore=0;
- HandLead=FindDealer();
-
- /* Loop until someone reaches 500 and there is no tie. */
-
- while (((PlayerScore<500)&&(CompScore<500))||(PlayerScore==CompScore))
- {
- SetUpScreen();
- InitVars();
- PrintScore();
- DealCards();
- GetBids();
- PrintBids();
- PlayHand();
- }
-
- FinishRoutine();
- }
- }
-
- /**********************************************************
- * Function: Title *
- * Parameters: none *
- * Return Values: none *
- * Purpose: draw title graphics. *
- **********************************************************/
- void Title()
- {
- int i=0;
-
- SetRast(RP,BLUP); /* Clear screen */
- SetAPen(RP,YELP);
- SetBPen(RP,BLUP);
-
- /* Draw card backs */
-
- for (i=0; i<6 ; i++)
- {
- DrawImage(RP,&Image25,(i*50)+15,65);
- }
-
- /* Flip S */
-
- Delay(5);
- DrawImage(RP,&Image24,15,65);
- Delay(5);
- DrawImage(RP,&Image23,15,65);
- Delay(5);
- DrawImage(RP,&Image22,15,65);
- Delay(5);
- DrawImage(RP,&Image21,15,65);
- Delay(5);
- DrawImage(RP,&Image17,15,65);
- Delay(5);
- DrawImage(RP,&Image18,15,65);
- Delay(5);
- DrawImage(RP,&Image19,15,65);
- Delay(5);
- DrawImage(RP,&Image20,15,65);
-
- /* Flip P */
-
- Delay(5);
- DrawImage(RP,&Image24,65,65);
- Delay(5);
- DrawImage(RP,&Image23,65,65);
- Delay(5);
- DrawImage(RP,&Image22,65,65);
- Delay(5);
- DrawImage(RP,&Image21,65,65);
- Delay(5);
- DrawImage(RP,&Image13,65,65);
- Delay(5);
- DrawImage(RP,&Image14,65,65);
- Delay(5);
- DrawImage(RP,&Image15,65,65);
- Delay(5);
- DrawImage(RP,&Image16,65,65);
-
- /* Flip A */
-
- Delay(5);
- DrawImage(RP,&Image24,115,65);
- Delay(5);
- DrawImage(RP,&Image23,115,65);
- Delay(5);
- DrawImage(RP,&Image22,115,65);
- Delay(5);
- DrawImage(RP,&Image21,115,65);
- Delay(5);
- DrawImage(RP,&Image9,115,65);
- Delay(5);
- DrawImage(RP,&Image10,115,65);
- Delay(5);
- DrawImage(RP,&Image11,115,65);
- Delay(5);
- DrawImage(RP,&Image12,115,65);
-
- /* Flip D */
-
- Delay(5);
- DrawImage(RP,&Image24,165,65);
- Delay(5);
- DrawImage(RP,&Image23,165,65);
- Delay(5);
- DrawImage(RP,&Image22,165,65);
- Delay(5);
- DrawImage(RP,&Image21,165,65);
- Delay(5);
- DrawImage(RP,&Image5,165,65);
- Delay(5);
- DrawImage(RP,&Image6,165,65);
- Delay(5);
- DrawImage(RP,&Image7,165,65);
- Delay(5);
- DrawImage(RP,&Image8,165,65);
-
- /* Flip E */
-
- Delay(5);
- DrawImage(RP,&Image24,215,65);
- Delay(5);
- DrawImage(RP,&Image23,215,65);
- Delay(5);
- DrawImage(RP,&Image22,215,65);
- Delay(5);
- DrawImage(RP,&Image21,215,65);
- Delay(5);
- DrawImage(RP,&Image1,215,65);
- Delay(5);
- DrawImage(RP,&Image2,215,65);
- Delay(5);
- DrawImage(RP,&Image3,215,65);
- Delay(5);
- DrawImage(RP,&Image4,215,65);
-
- /* Flip S */
-
- Delay(5);
- DrawImage(RP,&Image24,265,65);
- Delay(5);
- DrawImage(RP,&Image23,265,65);
- Delay(5);
- DrawImage(RP,&Image22,265,65);
- Delay(5);
- DrawImage(RP,&Image21,265,65);
- Delay(5);
- DrawImage(RP,&Image17,265,65);
- Delay(5);
- DrawImage(RP,&Image18,265,65);
- Delay(5);
- DrawImage(RP,&Image19,265,65);
- Delay(5);
- DrawImage(RP,&Image20,265,65);
-
- /* Prompt for pause */
-
- Move(RP,50,180);
- Text(RP,"Click any mouse button...",25);
-
- ReadMouse(); /* Pause for click */
- }
-
- /**********************************************************
- * Function: FindDealer *
- * Parameters: none *
- * Return Values: the player determined to initially deal. *
- * Purpose: find out who deals first in a game. *
- **********************************************************/
- int FindDealer()
- {
- int player=0, card=0, i;
- BOOL done=FALSE;
-
- SetRast(RP,BLUP); /* Clear Screen */
- SetAPen(RP,YELP);
- SetBPen(RP,BLUP);
-
- for (i=0 ; i<52 ; i++) Deck[i]=0; /* Set deck to undealt */
-
- Move(RP,70,70); /* Warn player of what's happening */
- Text(RP,"Ace of Spades",13);
- Move(RP,98,78);
- Text(RP,"deals",5);
-
- while(!done) /* Loop until dealer found */
- {
- while(Deck[card=rand()%52]) ; /* Find undealt card */
- Deck[card]=1; /* Mark card as dealt */
- DrawCard(CardX[player],CardY[player],card);
- /* Draw card */
- Delay(10); /* Pause */
- if (card==51) /* Ace of Spades */
- {
- done=TRUE;
- Move(RP,MsgX[player],MsgY[player]);
- Text(RP,"*",1);
- }
- player=(++player)%4; /* Increment player */
- }
-
- Move(RP,200,150); /* Wait for player */
- Text(RP,"Click mouse",11);
- ReadMouse();
-
- SetRast(RP,BLUP);
- return((++player)%4); /* Must return player 2 to left of */
- /* dealer. Program will later */
- /* decrement player to find lead */
- /* who should be to left of dealer */
- }
-
- /**********************************************************
- * Function: SetUpScreen *
- * Parameters: none *
- * Return Values: none *
- * Purpose: gets the screen ready for a new hand. *
- **********************************************************/
- void SetUpScreen()
- {
- /* Clear the Screen */
-
- SetRast(RP,BLUP);
-
- /* Draw the Score Box */
-
- SetAPen(RP,YELP);
- SetBPen(RP,BLKP);
- Move(RP,224,6);
- Text(RP," YOU CMP ",11);
- Move(RP,224,14);
- Text(RP,"SCORE SCORE",11);
- Move(RP,224,22);
- Text(RP," ",11);
- Move(RP,224,30);
- Text(RP," BID BID ",11);
- Move(RP,224,38);
- Text(RP," ",11);
- Move(RP,224,46);
- Text(RP,"TRICK TRICK",11);
- Move(RP,224,54);
- Text(RP," ",11);
- SetAPen(RP,WHTP);
- Move(RP,224,7);
- Draw(RP,312,7);
- Move(RP,267,0);
- Draw(RP,267,55);
- }
-
- /**********************************************************
- * Function: InitVars *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Initialize variables and arrays for a new hand.*
- **********************************************************/
- void InitVars()
- {
- int i;
-
- /* Set Leader */
-
- HandLead=(--HandLead+4)%4;
- TrickLead=HandLead;
-
- /* Reset HighCardLeft */
-
- HighCardLeft[0]=12;
- HighCardLeft[1]=12;
- HighCardLeft[2]=12;
- HighCardLeft[3]=12;
-
- /* Reset OutOfSuit */
-
- for (i=0 ; i<4 ; i++)
- {
- OutOfSuit[i][DIAMONDS]=FALSE;
- OutOfSuit[i][CLUBS] =FALSE;
- OutOfSuit[i][HEARTS] =FALSE;
- OutOfSuit[i][SPADES] =FALSE;
- }
-
- /* Determine Modes */
-
- for (i=0 ; i<4 ; i++)
- {
- Mode[i]=0;
- if (i==HandLead) Mode[i]+=2; /* Leader should bid higher */
- if (i==0||i==2) /* Human players -- check score */
- {
- if ((PlayerScore>400)&&(CompScore<350)) Mode[i]-=1;
- if (PlayerScore<(CompScore-100)) Mode[i]+=1;
- if (PlayerScore<(CompScore-200)) Mode[i]+=1;
- if (PlayerScore>(CompScore+100)) Mode[i]-=1;
- }
- if (i==1||i==3) /* Computer players -- check score */
- {
- if ((CompScore>400)&&(PlayerScore<350)) Mode[i]-=1;
- if (CompScore<(PlayerScore-100)) Mode[i]+=1;
- if (CompScore<(PlayerScore-200)) Mode[i]+=1;
- if (CompScore>(PlayerScore+100)) Mode[i]-=1;
- }
- }
- }
-
- /**********************************************************
- * Function: DealCards *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Shuffle & deal the deck to the players. *
- **********************************************************/
- void DealCards()
- {
- int i,j,player,cardnum[4];
-
- for (i=0 ; i<4 ; i++) cardnum[i]=0; /* Reset cards for each player */
- for (i=0 ; i<52 ; i++) Deck[i]=0; /* Set whole deck to undealt */
-
- /* Shuffle and Deal Deck */
-
- for (i=0 ; i<52 ; i++)
- {
- while(Deck[j=rand()%52]) ; /* Find undealt card */
- Deck[j]=((i/13)+1); /* Store owning player */
- }
-
- /* Transfer cards to player hands */
-
- for (i=0 ; i<52 ; i++)
- {
- player=Deck[i]-1; /* Get owning player */
- Hand[player][cardnum[player]++]=i+1; /* Store card, increment counter */
- }
- }
-
- /**********************************************************
- * Function: ShowHand *
- * Parameters: none *
- * Return Values: none *
- * Purpose: To display the player's hand. *
- **********************************************************/
- void ShowHand()
- {
- int i;
-
- /* Erase old hand */
-
- SetAPen(RP,BLUP);
- SetOPen(RP,BLUP);
- RectFill(RP,21,145,183,186);
-
- /* Draw each card, overlaying part of the previous one */
-
- for (i=0 ; i<13 ; i++)
- {
- if (Hand[0][i]) /* Only draw if card hasn't been played */
- DrawCard(((i*10)+21),145,((Hand[0][i])-1));
- }
- }
-
- /**********************************************************
- * Function: GetBids *
- * Parameters: none *
- * Return values: none *
- * Purpose: Get each player's bid. *
- **********************************************************/
- void GetBids()
- {
- int i;
-
- for (i=0 ; i<4 ; i++) Bid[i]=0; /* Reset bids for each player */
-
- /* Loop through each player */
-
- i=HandLead;
- do
- {
- if (i)
- Bid[i]=CalcBid(i); /* Computer Player */
- else
- Bid[i]=GetPlayerBid(); /* Human Player */
- i=(++i)%4;
- } while (i!=HandLead);
-
- /* Calculate team contracts */
-
- PlayerBid=Bid[0]+Bid[2];
- CompBid=Bid[1]+Bid[3];
-
- /* Pause for click */
-
- ReadMouse();
-
- /* Erase Bids */
-
- SetBPen(RP,BLUP);
- for (i=0 ; i<4 ; i++)
- {
- Move(RP,MsgX[i],MsgY[i]);
- Text(RP," ",1);
- }
- }
-
- /**********************************************************
- * Function: GetPlayerBid *
- * Parameters: none *
- * Return Values: bid -- number of tricks bid *
- * Purpose: Get the human player's bid. Could use gadgets, *
- * but this is easier to program. *
- **********************************************************/
- int GetPlayerBid()
- {
- int bid=1,length;
- BOOL havebid=FALSE;
-
- ShowHand();
-
- /* Draw input box */
-
- SetAPen(RP,YELP);
- SetBPen(RP,BLKP);
- Move(RP,258,142);
- Text(RP,"BID",3);
- Move(RP,250,150);
- Text(RP," + ",5);
- Move(RP,250,158);
- Text(RP," OK",5);
- Move(RP,250,166);
- Text(RP," - ",5);
-
- /* Loop until OK is clicked */
-
- while(!havebid)
- {
-
- /* Draw Current Bid */
-
- SetAPen(RP,GRNP);
- SetBPen(RP,BLKP);
- Move(RP,250,158);
- Text(RP," ",2);
- itoa(bid,String);
- length=strlen(String);
- Move(RP,(258-(4*length)),158);
- Text(RP,String,length);
-
- /* Wait for Mouse input */
-
- ReadMouse();
- if (Button==MLEFT) /* Left Button Pressed */
- {
- if ((Mx>265)&&(Mx<274)&&(My>143)&&(My<152)) bid++; /* plus sign */
- if ((Mx>273)&&(Mx<290)&&(My>151)&&(My<160)) havebid=TRUE; /* OK */
- if ((Mx>265)&&(Mx<274)&&(My>159)&&(My<168)) bid--; /* minus sign */
- }
- if (Button==MRIGHT) /* Right Button Pressed */
- {
- bid=CalcBid(0); /* Suggest a Bid */
- }
-
- /* Make sure bid is valid */
-
- if (bid<1) bid=1;
- if (bid>12) bid=12;
- }
-
- /* Erase Input Box */
-
- SetAPen(RP,BLUP);
- SetOPen(RP,BLUP);
- RectFill(RP,250,135,291,168);
-
- /* Display the bid */
-
- SetAPen(RP,YELP);
- SetBPen(RP,BLUP);
- itoa(bid,String);
- Move(RP,MsgX[0],MsgY[0]);
- Text(RP,String,strlen(String));
-
- /* Send the bid back */
-
- return(bid);
- }
-
- /**********************************************************
- * Function: CalcBid *
- * Parameters: player -- number of player to calculate for *
- * Return Values: bid -- number of tricks *
- * Purpose: To calculate the number of tricks bid by a *
- * player. *
- **********************************************************/
- int CalcBid(player)
- int player;
- {
- int i,j,numsuit,points,suit,bid;
-
- points=0;
-
- /* Add up points for the non-spades suits */
-
- for (i=DIAMONDS ; i<SPADES ; i++) /* Loop thru suits */
- {
- numsuit=0;
- suit=i*13;
-
- /* Count cards for suit and add appropriate points */
-
- for (j=0 ; j<13 ; j++)
- {
- if (Deck[suit+j]==player+1) numsuit++;
- }
- points+=SuitPoints[0][numsuit];
-
- /* Add points for face cards */
-
- if (Deck[suit+12]==player+1) points+=4; /* Ace */
- if (Deck[suit+11]==player+1) points+=3; /* King */
- if (Deck[suit+10]==player+1) points+=2; /* Queen */
- }
-
- /* Calculate spades */
-
- numsuit=0;
-
- /* Count Spades and add appropriate points */
-
- for (j=39 ; j<52 ; j++)
- {
- if (Deck[j]==player+1) numsuit++;
- }
- points+=SuitPoints[1][numsuit];
-
- /* Add points for Face Cards */
-
- if (Deck[51]==player+1) points+=4; /* Ace */
- if (Deck[50]==player+1) points+=3; /* King */
- if (Deck[49]==player+1) points+=2; /* Queen */
- if (Deck[48]==player+1) points+=1; /* Jack */
-
- points+=Mode[player]; /* Adjust for aggressiveness */
- if (points<4) points=4; /* Validate number of points */
- bid=points/4; /* Find Bid */
-
- /* Make sure total team bid not greater than 13 */
-
- i=(player+2)%4; /* Find partner */
- if ((bid+Bid[i])>13) bid=13-Bid[i];
-
- /* Display Bid */
-
- itoa(bid,String);
- SetAPen(RP,YELP);
- SetBPen(RP,BLUP);
- Move(RP,MsgX[player],MsgY[player]);
- Text(RP,String,strlen(String));
-
- /* Send bid back */
-
- return(bid);
- }
-
- /**********************************************************
- * Function: PlayHand *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Play out a hand until all 13 tricks are taken. *
- **********************************************************/
- void PlayHand()
- {
- int i;
-
- /* Initialize */
-
- PlayerTricks=CompTricks=0;
- SpadePlayed=FALSE;
- PrintTricks();
-
- /* Loop through all 13 tricks */
-
- for (i=0 ; i<13 ; i++)
- {
- TrickLead=TakeTrick(); /* Play a trick */
- if ((TrickLead==0)||(TrickLead==2)) /* Who won? */
- PlayerTricks++;
- else
- CompTricks++;
- PrintTricks(); /* Display new trick total */
-
- /* Indicate who won with an '*' */
-
- SetAPen(RP,YELP);
- SetBPen(RP,BLUP);
- Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
- Text(RP,"*",1);
-
- /* Pause for click */
-
- ReadMouse();
-
- /* Erase winner indicator */
-
- Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
- Text(RP," ",1);
- }
-
- /* Calculate new score */
-
- if (PlayerTricks<PlayerBid)
- PlayerScore-=(10*PlayerBid);
- if (CompTricks<CompBid)
- CompScore-=(10*CompBid);
- if (PlayerTricks>=PlayerBid)
- PlayerScore+=((10*PlayerBid)+(PlayerTricks-PlayerBid));
- if (CompTricks>=CompBid)
- CompScore+=((10*CompBid)+(CompTricks-CompBid));
-
- /* Pause for click */
-
- ReadMouse();
- }
-
- /**********************************************************
- * Function: TakeTrick *
- * Parameters: none *
- * Return Values: winner of trick *
- * Purpose: Each player plays a card, then determine trick *
- * winner. *
- **********************************************************/
- int TakeTrick()
- {
- int i,j,leadsuit,suit,value;
-
- /* Clear previously played cards */
-
- SetAPen(RP,BLUP);
- SetOPen(RP,BLUP);
- for (i=0 ; i<4 ; i++) RectFill(RP,CardX[i],CardY[i],(CardX[i]+41),(CardY[i]+41));
-
- /* Get played cards */
-
- i=TrickLead;
- do
- {
- if (!i)
- Card[i]=GetPlayerCard();
- else
- Card[i]=GetCompCard(i);
- if (i==TrickLead) /* First card played wins so far */
- {
- HighCard=Card[i];
- leadsuit=Card[i]/13;
- Winner=i;
- }
- else
- {
- suit=Card[i]/13;
-
- /* See if this card is the new winner */
-
- if (((suit==leadsuit)||(suit==SPADES))&&(Card[i]>HighCard))
- {
- HighCard=Card[i];
- Winner=i;
- }
-
- /* Was player out of the lead suit ? */
-
- if (suit!=leadsuit) OutOfSuit[i][leadsuit]=TRUE;
- }
- i=(++i)%4;
- } while (i!=TrickLead);
-
- ShowHand();
-
- /* Set highest card played in each suit */
-
- for (i=0 ; i<4 ; i++)
- {
- for (j=0 ; j<4 ; j++) /* Need two loops to make sure we get all */
- {
- value=Card[j]%13;
- suit=Card[j]/13;
- if (value==HighCardLeft[suit]) HighCardLeft[suit]=value-1;
- }
- }
-
- /* Send back trick winner */
-
- return(Winner);
- }
-
- /**********************************************************
- * Function: GetPlayerCard *
- * Parameters: none *
- * Return Values: card picked to play *
- * Purpose: Allow player to pick card to play. *
- **********************************************************/
- int GetPlayerCard()
- {
- int i,x,card;
-
- /* Let player know that it's his/her turn */
-
- SetBPen(RP,BLUP);
- SetAPen(RP,YELP);
- Move(RP,200,150);
- Text(RP,"PLAY A CARD",11);
-
- /* Loop until we get a good card */
-
- FOREVER
- {
- ReadMouse(); /* Wait for mouse click */
- if (Button==MRIGHT) SuggestCard(); /* Player wants a suggestion */
- if (Button==MLEFT) /* Did player pick a card ? */
- {
- for (i=12 ; i>=0 ; i--) /* Check from right to left */
- {
- x=(i*10)+21; /* Set left corner for card */
-
- /* See if clicked inside this card and if card is still unplayed */
-
- if ((My<187)&&(My>144)&&(Mx<(x+42))&&(Mx>=x)&&(Hand[0][i]))
- {
- if (ValidCard(i)) /* Was this a playable card ? */
- {
- card=Hand[0][i]-1;
- Hand[0][i]=0; /* Mark card as played */
- if ((card/13)==SPADES) SpadePlayed=TRUE; /* Spades have been broken */
-
- /* Erase suggestion '*' */
-
- SetAPen(RP,BLUP);
- SetOPen(RP,BLUP);
- RectFill(RP,21,136,170,144);
-
- DrawCard(CardX[0],CardY[0],card); /* Draw played card */
-
- /* Erase prompt message */
-
- SetBPen(RP,BLUP);
- Move(RP,200,150);
- Text(RP," ",11);
-
- /* Send back played card */
-
- return(card);
- }
- else
-
- /* if chosen card was not valid, need a new card */
-
- i=-1;
- }
- }
- }
- }
- }
-
- /**********************************************************
- * Function: ValidCard *
- * Parameters: card -- card in player's hand to check *
- * Return Values: was card valid or not? *
- * Purpose: To determine if the card chosen by the player *
- * was valid or not. *
- **********************************************************/
- BOOL ValidCard(card)
- int card;
- {
- int i,suit,leadsuit;
-
- SuitNumber[DIAMONDS]=0;
- SuitNumber[CLUBS] =0;
- SuitNumber[HEARTS] =0;
- SuitNumber[SPADES] =0;
-
- /* Count number of cards player has in each suit */
-
- for (i=0 ; i<13 ; i++)
- {
- if (Hand[0][i]) SuitNumber[(Hand[0][i]-1)/13]++;
- }
-
- suit=(Hand[0][card]-1)/13; /* Find suit of played card */
-
- if (!TrickLead) /* Player is leading */
- {
- /* If he didn't lead a spade, it was a good play */
- if (suit!=SPADES) return(TRUE);
-
- /* If he only has spades, he has no choice */
- if ((!SuitNumber[0])&&(!SuitNumber[1])&&(!SuitNumber[2])) return(TRUE);
-
- /* If spades have been played, he can lead anything */
- if (SpadePlayed) return(TRUE);
-
- /* Must have lead a spade when it was illegal to */
- return(FALSE);
- }
-
- /* Player doesn't lead */
-
- leadsuit=Card[TrickLead]/13; /* Find suit that was lead */
-
- /* If he played the suit that was lead, he is OK */
- if (suit==leadsuit) return(TRUE);
-
- /* If he didn't have any, he's OK */
- if (!SuitNumber[leadsuit]) return(TRUE);
-
- /* Must have had some but didn't play them */
- return(FALSE);
- }
-
- /**********************************************************
- * Function: CountCards *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Count cards in each suit for a player. *
- * Determine short and long suits. *
- **********************************************************/
- void CountCards(player)
- int player;
- {
- int i,card,suit,maximum,minimum;
-
- /* Initialization */
-
- SuitNumber[DIAMONDS]=0;
- SuitNumber[CLUBS] =0;
- SuitNumber[HEARTS] =0;
- SuitNumber[SPADES] =0;
-
- /* Loop through all cards in the player's hand */
-
- for (i=0 ; i<13 ; i++)
- {
- if (Hand[player][i]) /* Make sure card hasn't been played */
- {
- card=Hand[player][i]-1;
- suit=card/13;
- Value[i]=6-(card%13); /* Give lower cards a slight priority */
- SuitNumber[suit]++; /* Count Number of Suit held */
- }
- else
- Value[i]=-10000; /* Don't throw previously played cards */
- }
-
- /* Find short and long suits */
-
- minimum=14;
- maximum=0;
- ShortSuit=LongSuit=3;
- for (i=DIAMONDS ; i<SPADES ; i++)
- {
- if ((SuitNumber[i]<minimum)&&(SuitNumber[i]>0))
- {
- minimum=SuitNumber[i];
- ShortSuit=i;
- }
- if (SuitNumber[i]>maximum)
- {
- maximum=SuitNumber[i];
- LongSuit=i;
- }
- }
- }
-
- /**********************************************************
- * Function: SuggestCard *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Suggest a card for player to play. *
- **********************************************************/
- void SuggestCard()
- {
- int i,pick,maximum;
-
- CountCards(0);
-
- /* Go to appropriate point calculating routine */
-
- if (!TrickLead)
- CalcLead(0);
- else
- CalcFollow(0);
-
- /* Find best card (the one with the most points) */
-
- pick=0;
- maximum=Value[0];
- for (i=1 ; i<13 ; i++)
- {
- if (Value[i]>maximum)
- {
- maximum=Value[i];
- pick=i;
- }
- }
-
- /* Display an '*' over suggested card */
-
- SetAPen(RP,YELP);
- SetBPen(RP,BLUP);
- Move(RP,((pick*10))+22,142);
- Text(RP,"*",1);
- }
-
- /**********************************************************
- * Function: GetCompCard *
- * Parameters: player -- player to play *
- * Return Values: card played *
- * Purpose: Determine which card a computer-controlled *
- * player will play. *
- **********************************************************/
- int GetCompCard(player)
- int player;
- {
- int i,pick,card,maximum;
-
- CountCards(player);
-
- /* Go to appropriate point calculating routine */
-
- if (player==TrickLead)
- CalcLead(player);
- else
- CalcFollow(player);
-
- /* Find best card (the one with the most points) */
-
- pick=0;
- maximum=Value[0];
- for (i=1 ; i<13 ; i++)
- {
- if (Value[i]>maximum)
- {
- maximum=Value[i];
- pick=i;
- }
- }
-
- card=Hand[player][pick]-1;
- if ((card/13)==3) SpadePlayed=TRUE; /* Mark that spades have been broken */
- Hand[player][pick]=0; /* Card has now been played */
- DrawCard(CardX[player],CardY[player],card); /* Draw the played card */
- return(card); /* Send the played card back */
- }
-
- /**********************************************************
- * Function: CalcLead *
- * Parameters: player -- whose hand to calculate *
- * Return Values: none *
- * Purpose: To calculate the value of each card in a hand *
- * to determine which card should be played if *
- * the hand is leading. *
- **********************************************************/
- void CalcLead(player)
- int player;
- {
- int i,card,suit,value;
- BOOL opponentsout=FALSE, partnerout=FALSE;
-
- /* Loop through all cards in hand */
-
- for (i=0 ; i<13 ; i++)
- {
- if (Hand[player][i]) /* Make sure card hasn't been played */
- {
-
- /* Find suit and face value */
-
- card=Hand[player][i]-1;
- suit=card/13;
- value=card%13;
-
- if ((OutOfSuit[(player+1)%4][suit])||(OutOfSuit[(player+3)%4][suit]))
- opponentsout=TRUE;
-
- if (OutOfSuit[(player+2)%4][suit])
- partnerout=TRUE;
-
- if (value==HighCardLeft[suit]) /* Card is highest left in a suit */
- {
- if (suit==SPADES) /* Spades don't matter if someone is */
- Value[i]+=50; /* out. */
- else
- {
- if (opponentsout) /* If opponents are out, don't waste */
- Value[i]-=50; /* high cards. */
- else
- Value[i]+=50;
- }
- }
-
- /* If player holds spades, get rid of short suit */
- if ((SuitNumber[SPADES])&&(suit==ShortSuit)) Value[i]+=250;
-
- /* If player doesn't hold spades, get rid of long suit */
- if ((!SuitNumber[SPADES])&&(suit==LongSuit)) Value[i]+=250;
-
- /* If spades aren't broken, they can't be lead */
- if ((suit==SPADES)&&(!SpadePlayed)) Value[i]-=5000;
-
- /* Lead suits your partner is out of */
- if ((suit!=SPADES)&&(partnerout)&&(!opponentsout)) Value[i]+=300;
- }
- }
- }
-
- /**********************************************************
- * Function: CalcFollow *
- * Parameters: player -- whose hand to calculate *
- * Return Values: none *
- * Purpose: To calculate the value of each card in a hand *
- * to determine which card should be played if *
- * the hand is not leading. *
- **********************************************************/
- void CalcFollow(player)
- int player;
- {
- int i,card,suit,value,leadsuit;
- BOOL alreadywon;
-
- leadsuit=Card[TrickLead]/13; /* Calculate the suit that was lead */
-
- /* See if partner has already won the trick */
-
- alreadywon=FALSE;
- /* See if win is guaranteed (player is last to play) */
- if ((Winner==((player+2)%4))&&(TrickLead==((player+1)%4)))
- alreadywon=TRUE;
-
- /* See if win is probable (player is next to last to play) */
- if ((Winner==TrickLead)&&(TrickLead==((player+2)%4)))
- {
- value=Card[TrickLead]%13;
- if ((value==HighCardLeft[leadsuit])&&(value>9)) alreadywon=TRUE;
- }
-
- /* Loop through all cards in hand */
-
- for (i=0 ; i<13 ; i++)
- {
- if (Hand[player][i]) /* Make sure card hasn't been played */
- {
-
- /* Find suit and face value of card */
-
- card=Hand[player][i]-1;
- suit=card/13;
- value=card%13;
-
- if (suit==leadsuit) /* Card is of lead suit */
- {
- Value[i]+=5000;
-
- /* If it is the highest one left in that suit, throw it */
- if ((value==HighCardLeft[suit])&&(TrickLead!=((player+1)%4))&&(card>HighCard))
- Value[i]+=70;
-
- /* See if card will beat those previously played */
- if (card>HighCard)
- {
- if (!alreadywon) /* Team hasn't won yet */
- {
- if (TrickLead==((player+1)%4)) /* Can definitely take trick */
- Value[i]+=100;
- else
- Value[i]+=10; /* Maybe take trick */
- }
- else
- Value[i]-=75; /* If the team has one, hold high cards */
- }
-
- /* If team has already one the trick, throw low cards */
- if ((card<HighCard)&&alreadywon) Value[i]+=75;
- }
-
- /* If player is going to throw a spade, make sure it has a chance of
- winning */
- if ((suit==SPADES)&&(card>HighCard))
- {
- if (!alreadywon)
- Value[i]+=10; /* If team hasn't won, throw the spade */
- else
- Value[i]-=1000; /* If team has won, hold high spades */
- }
- if ((suit==SPADES)&&(card<HighCard))
- {
- if (!alreadywon)
- Value[i]-=1000; /* If the team hasn't won, don't throw a losing spade */
- else
- Value[i]+=10; /* If the team has one, throw a low spade */
- }
-
- /* If player is out of the lead suit, don't throw important cards
- in other suits */
- if ((suit!=leadsuit)&&(value==HighCardLeft[suit])) Value[i]-=100;
-
- /* If player is out of lead suit, let's see about trumping */
- if ((!SuitNumber[leadsuit])&&(suit==SPADES))
- {
- if (!alreadywon)
- Value[i]+=100; /* If team hasn't won, trump */
- else
- Value[i]-=1000; /* If team has won, no need to trump */
- }
-
- /* If player is out of lead suit and out of spades, throw the long
- suit left (keep as many suits as possible in hand) */
- if ((!SuitNumber[leadsuit])&&(!SuitNumber[SPADES])&&(suit==LongSuit))
- {
- Value[i]+=100;
- }
-
- /* Give short suit a priority */
- if (suit==ShortSuit) Value[i]+=45;
- }
- }
- }
-
- /**********************************************************
- * Function: PrintBids *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Display the number of tricks bid by each team *
- * in the score box. *
- **********************************************************/
- void PrintBids()
- {
- int length=0;
-
- SetAPen(RP,GRNP);
- SetBPen(RP,BLKP);
- itoa(PlayerBid,String);
- length=strlen(String);
- Move(RP,(244-(4*length)),38);
- Text(RP,String,length);
- itoa(CompBid,String);
- length=strlen(String);
- Move(RP,(292-(4*length)),38);
- Text(RP,String,length);
- }
-
- /**********************************************************
- * Function: PrintScore *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Display each team's score in the score box. *
- **********************************************************/
- void PrintScore()
- {
- int length=0;
-
- SetAPen(RP,GRNP);
- SetBPen(RP,BLKP);
- itoa(PlayerScore,String);
- length=strlen(String);
- Move(RP,(244-(4*length)),22);
- Text(RP,String,length);
- itoa(CompScore,String);
- length=strlen(String);
- Move(RP,(292-(4*length)),22);
- Text(RP,String,length);
- }
-
- /**********************************************************
- * Function: PrintTricks *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Display the number of tricks taken by each *
- * team in the score box. *
- **********************************************************/
- void PrintTricks()
- {
- int length=0;
-
- SetAPen(RP,GRNP);
- SetBPen(RP,BLKP);
- itoa(PlayerTricks,String);
- length=strlen(String);
- Move(RP,(244-(4*length)),54);
- Text(RP,String,length);
- itoa(CompTricks,String);
- length=strlen(String);
- Move(RP,(292-(4*length)),54);
- Text(RP,String,length);
- }
-
- /**********************************************************
- * Function: ReadMouse *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Wait for mouse input, and update the mouse *
- * variables accordingly. *
- **********************************************************/
- void ReadMouse()
- {
- ULONG class;
- USHORT code;
- BOOL gotmouse=FALSE;
-
- /* Loop until we have a mouse message */
-
- while(!gotmouse)
- {
-
- /* Wait for Intuition Message */
-
- if ((Message=(struct IntuiMessage *) GetMsg(Wdw->UserPort)) == NULL)
- {
- Wait(1L<<Wdw->UserPort->mp_SigBit);
- continue;
- }
-
- /* Interpret Message */
-
- class = Message->Class;
- code = Message->Code;
- Mx=((SHORT) Message->MouseX) - 4; /* Adjustments for */
- My=((SHORT) Message->MouseY) - 12; /* GIMMEZEROZERO Window */
-
- /* See if Window Close Box clicked */
-
- if (class & CLOSEWINDOW) WrapUp();
-
- /* Otherwise, make sure Message was caused by mouse */
-
- if (class & MOUSEBUTTONS)
- {
- switch(code)
- {
-
- /* Left Button Released */
-
- case SELECTUP:
- Button=MLEFT;
- gotmouse=TRUE;
- break;
-
- /* Right Button Released */
-
- case MENUUP:
- Button=MRIGHT;
- gotmouse=TRUE;
- break;
-
- /* Other Input */
-
- default:
- gotmouse=FALSE;
- }
- }
- ReplyMsg(Message);
- }
- }
-
- /**********************************************************
- * Function: DrawCard *
- * Parameters: x -- x coordinate of top left corner *
- * y -- y coordinate of top left corner *
- * card -- number of card to draw *
- * Return Values: none *
- * Purpose: Draw a card. *
- **********************************************************/
- void DrawCard(x, y, card)
- int x, y, card;
- {
- CardImage.ImageData = (UWORD *)(CardData+card*126*6);
- DrawImage(RP, &CardImage, x, y);
- }
-
- /**********************************************************
- * Function: FinishRoutine *
- * Parameters: none *
- * Return Values: none *
- * Purpose: Display final score, ask to play again. *
- **********************************************************/
- void FinishRoutine()
- {
- BOOL haveinput;
-
- SetRast(RP,BLUP);
-
- SetAPen(RP,WHTP);
- SetBPen(RP,BLUP);
-
- Move(RP,112,56);
- Text(RP,"FINAL SCORE:",12);
- Move(RP,80,72);
- Text(RP,"YOU:",4);
- Move(RP,184,72);
- Text(RP,"ME:",3);
- SetAPen(RP,YELP);
- itoa(PlayerScore,String);
- Move(RP,116,72);
- Text(RP,String,strlen(String));
- itoa(CompScore,String);
- Move(RP,212,72);
- Text(RP,String,strlen(String));
-
- Move(RP,112,96);
- Text(RP,"PLAY AGAIN ?",12);
- SetAPen(RP,BLKP);
- SetBPen(RP,WHTP);
- Move(RP,112,112);
- Text(RP,"YES",3);
- Move(RP,188,112);
- Text(RP,"NO",2);
-
- haveinput=FALSE;
- while (!haveinput)
- {
- ReadMouse();
- if ((Mx>111)&&(Mx<136)&&(My>105)&&(My<114))
- {
- haveinput=TRUE;
- AllDone=FALSE;
- }
- if ((Mx>187)&&(Mx<204)&&(My>105)&&(My<114))
- {
- haveinput=TRUE;
- AllDone=TRUE;
- }
- }
- }
-
- /**********************************************************
- * Function: itoa *
- * Parameters: n -- number to convert *
- * s -- pointer to result string *
- * Return Values: none *
- * Purpose: Convert an integer to a string so it can be *
- * used by the Text function. Lattice does not *
- * have one. *
- **********************************************************/
- void itoa(n,s)
- char *s;
- int n;
- {
- int i=0;
- BOOL sign=FALSE;
-
- if (n<0)
- {
- sign=TRUE;
- n=-n;
- }
- do
- {
- s[i++]=n%10+'0';
- } while((n/=10)>0);
- if (sign) s[i++]='-';
- s[i]='\0';
- strrev(s);
- }
-